<script setup lang="ts">
import { watch, ref, onBeforeUpdate, useTemplateRef, computed } from 'vue';
import { useScroll } from '@vueuse/core';
import Menu from '@/views/main/components/Menu';
import { useAppStore, useCategoryStore } from '@/store';
import type { Category } from '../../types';

const categoryStore = useCategoryStore();
const categories = computed(() => categoryStore.categoriesGetter);

const appStore = useAppStore();
const currentCategoryIndex = computed(
  () => appStore.currentCategoryIndexGetter
);

const isVisible = ref<boolean>(false);
const onPopupShow = () => (isVisible.value = true);

// 所有的 item 元素
let itemRefs: HTMLLIElement[] = [];
// 组件更新前，清空 itemRefs
onBeforeUpdate(() => {
  itemRefs = [];
});
const setItemRef = (el: HTMLLIElement) => {
  if (el) {
    itemRefs.push(el);
  }
};

const sliderStyle = ref({
  transform: `translateX(0px)`,
  width: 52 + 'px'
});

// 获取 ul 元素
const ulRef = useTemplateRef<HTMLUListElement>('ulRef');
// 获取 ul 滚动距离
const { x: ulElemScrollLeft } = useScroll(ulRef);

watch(currentCategoryIndex, newVal => {
  const rect = (itemRefs[newVal] as HTMLElement).getBoundingClientRect();
  const { left, width } = rect;

  sliderStyle.value = {
    // 滑块的位置 = ul 横向滚动的位置 + 当前元素的 left - ul 的 padding
    transform: `translateX(${ulElemScrollLeft.value + left - 10}px)`,
    width: `${width}px`
  };
});

const onItemClick = (category: Category) => {
  appStore.changeCurrentCategory(category);

  isVisible.value = false;
};
</script>

<template>
  <div class="sticky top-0 left-0 z-10 bg-white dark:bg-zinc-900">
    <ul
      ref="ulRef"
      class="relative flex overflow-hidden overflow-x-auto p-1 text-xs text-zinc-600"
    >
      <!-- 滑块 -->
      <li
        :style="sliderStyle"
        class="absolute h-[22px] rounded-lg bg-zinc-900 duration-200 dark:bg-zinc-800"
      />
      <!-- 汉堡按钮 -->
      <li
        class="shadow-l-white dark:shadow-l-zinc fixed top-0 right-[-1px] z-20 flex h-4 w-4 items-center bg-white px-1 dark:bg-zinc-900"
        @click="onPopupShow"
      >
        <MSvgIcon name="hamburger" color="#000" fillClass="w-1.5 h-1.5" />
      </li>
      <!-- items -->
      <li
        v-for="(item, index) in categories"
        :key="item.id"
        class="z-10 shrink-0 px-1.5 py-0.5 duration-200 last:mr-4"
        :class="{
          'text-zinc-100': currentCategoryIndex === index
        }"
        :ref="el => setItemRef(el as HTMLLIElement)"
        @click="onItemClick(item)"
      >
        {{ item.name }}
      </li>
    </ul>
    <MPopup v-model="isVisible">
      <Menu :categories="categories" @onItemClick="onItemClick" />
    </MPopup>
  </div>
</template>
